/**
 * <AiRmob-Framework; A simple augmented reality framework for android >
    Copyright (C) <2012>  <AiRmob Team>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package rendercomponents;

import java.util.LinkedList;

public class Group extends Parent {

	protected LinkedList<Parent> children;

	/**
	 * Generates a group to which objects can be appended. All transformation on
	 * a group will be used for its children.
	 * 
	 * @param parent
	 */
	public Group(Parent parent) {
		super(parent);
		this.children = new LinkedList<Parent>();
		this.type = 2;
	}

	/**
	 * Adds a model3D to this group.
	 * 
	 * @param model
	 * @return Identifier that can be used for individually controlling this
	 *         instance.
	 */
	public Identifier add(Model3D model) {
		Scene scene = this.getScene();
		this.hasChildren = true;
		Identifier ID = new Identifier(this);
		ID.setChild(model);
		ID.holdsTransparentChild = model.isTransparent();
		if (model.isTransparent()) {
			scene.numTransparentModels++;
			if (scene.numTransparentModels >= 2
					&& scene.renderer.settings.decideSortingAuto)
				scene.renderer.settings.sortObjectsByDistance = true;
		}
		ID.type = 3;
		ID.colorID = scene.idNum;
		scene.idNum++;
		this.children.add(ID);
		this.getScene().notifyChange();
		return ID;
	}

	/**
	 * 
	 * Adds a group to this group.
	 * 
	 * @param group
	 */
	public void add(Group group) {
		this.hasChildren = true;
		group.parent = this;
		this.children.add(group);
		this.getScene().notifyChange();
	}

	/**
	 * Adds a light to this group.
	 * 
	 * @param light
	 * @return Identifier that can be used for individually controlling this
	 *         instance.
	 */
	public Identifier add(Light light) {
		Scene scene = this.getScene();

		if (scene.numLights < scene.renderer.settings.maxLights) {
			this.hasChildren = true;
			Identifier ID = new Identifier(this);
			ID.setLightChild(light);
			ID.type = 4;
			scene.numLights++;
			this.children.add(ID);
			this.getScene().notifyChange();
			return ID;
		} else {
			System.out
					.println("numLights > maxLights for this scene. There may be only as many lights as set in settings.maxLights.");
			return null;
		}
	}

	/**
	 * Adds an animation to this group.
	 * 
	 * @param animation
	 * @return Identifier that can be used for individually controlling this
	 *         instance.
	 */
	public Identifier add(ModelAnimation animation) {
		this.hasChildren = true;
		Identifier ID = new Identifier(this);
		ID.setAnimationChild(animation);
		ID.type = 7;
		ID.colorID = this.getScene().idNum;
		this.getScene().idNum++;
		this.children.add(ID);
		this.getScene().notifyChange();
		return ID;
	}

	/**
	 * 
	 * Adds a modelGroup to this group.
	 * 
	 * @param modelGroup
	 * @return Identifier that can be used for individually controlling this
	 *         instance.
	 */
	public Identifier add(ModelGroup modelGroup) {
		Scene scene = this.getScene();
		this.hasChildren = true;
		Identifier ID = new Identifier(this);
		ID.setModelGroupChild(modelGroup);
		ID.holdsTransparentChild = modelGroup.hasTransparentModel;
		if (modelGroup.hasTransparentModel) {
			scene.numTransparentModels++;
			if (scene.numTransparentModels >= 2
					&& scene.renderer.settings.decideSortingAuto)
				scene.renderer.settings.sortObjectsByDistance = true;
		}
		ID.type = 9;
		ID.colorID = scene.idNum;
		scene.idNum++;
		this.children.add(ID);
		this.getScene().notifyChange();
		return ID;
	}

	/**
	 * 
	 * Adds a text to this group.
	 * 
	 * @param text
	 * @return Identifier that can be used for individually controlling this
	 *         instance.
	 */
	public Identifier add(Text text) {
		this.hasChildren = true;
		Identifier ID = new Identifier(this);
		ID.setTextChild(text);
		ID.type = 11;
		this.children.add(ID);
		this.getScene().notifyChange();
		return ID;
	}

	/**
	 * 
	 * Removes a parent from this group. Notifies the scene that something has
	 * changed.
	 * 
	 * @param Parent
	 *            parent - the parent that shall be removed.
	 */
	public void remove(Parent parent) {
		this.children.remove(parent);
		this.getScene().notifyChange();
	}

}
